﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ScalarWrapper.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.Agent.Internal
{
  using System.Linq;

  using DataDuctus.Snmp.Persistor.Core.Attributes;
  using DataDuctus.Snmp.Persistor.Core.MetaData;
  using DataDuctus.Snmp.Persistor.Core.Persistor.Internal;

  using Lextm.SharpSnmpLib;
  using Lextm.SharpSnmpLib.Pipeline;

  /// <summary>
  /// The scalar wrapper.
  /// </summary>
  internal class ScalarWrapper : ScalarObject
  {
    #region Fields

    /// <summary>
    /// The instance.
    /// </summary>
    private readonly object instance;

    /// <summary>
    /// The property.
    /// </summary>
    private readonly PropertyMeta property;

    #endregion

    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="ScalarWrapper"/> class.
    /// </summary>
    /// <param name="property">
    /// The property.
    /// </param>
    /// <param name="instance">
    /// The instance.
    /// </param>
    /// <param name="oid">
    /// The oid.
    /// </param>
    internal ScalarWrapper(PropertyMeta property, object instance, ObjectIdentifier oid)
      : base(oid)
    {
      this.property = property;
      this.instance = instance;
    }

    #endregion

    #region Public Properties

    /// <summary>
    /// Gets or sets the data.
    /// </summary>
    /// <exception cref="AccessFailureException">If get and <see cref="PropertyAccess.WriteOnly"/>.</exception>
    public override ISnmpData Data
    {
      get
      {
        if (this.property.Access == PropertyAccess.WriteOnly)
        {
          throw new AccessFailureException(
            string.Format(
              "[Get] Property = {0} [Oid = {1}] has access = {2}", 
              this.property.Property.Name, 
              this.Variable.Id, 
              this.property.Access));
        }

        return DataConverter.ConvertToSnmpType(this.property, this.property.Property.GetValue(this.instance, null));
      }

      set
      {
        if (this.property.Access != PropertyAccess.ReadWrite && this.property.Access != PropertyAccess.WriteOnly)
        {
          throw new AccessFailureException(
            string.Format(
              "[Set] Property = {0} [Oid = {1}] has access = {2}", 
              this.property.Property.Name, 
              this.Variable.Id, 
              this.property.Access));
        }

        this.property.Property.SetValue(this.instance, DataConverter.ConvertToEntityType(this.property, value), null);
      }
    }

    #endregion

    #region Methods

    /// <summary>
    /// The create wrappers.
    /// </summary>
    /// <param name="clzMeta">
    /// The clz meta.
    /// </param>
    /// <param name="instance">
    /// The instance.
    /// </param>
    /// <returns>
    /// The SnmpPersistor.Core.Agent.Internal.ScalarWrapper[].
    /// </returns>
    internal static ScalarWrapper[] CreateWrappers(ClassMeta clzMeta, object instance)
    {
      if (!clzMeta.IsTable)
      {
        return (from property in clzMeta.Properties
                select
                  new ScalarWrapper(
                  property, instance, new ObjectIdentifier(string.Format("{0}.{1}", clzMeta.Oid, property.SubOid)))).ToArray();
      }

      return (from property in clzMeta.Properties
              select new ScalarWrapper(property, instance, IndexCreator.CreateIndex(clzMeta, property, instance))).ToArray();
    }

    #endregion
  }
}